﻿using System;
using System.IO;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;

namespace Local.Service
{
    public class XmlHelper
    {
        public static async Task Serialize<T>(T t, string fileName)
        {
            var folder = ApplicationData.Current.LocalFolder;
            try
            {
                StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
                using (IRandomAccessStream randomAccessSteam = await file.OpenAsync(FileAccessMode.ReadWrite))
                using (IOutputStream outputStream = randomAccessSteam.GetOutputStreamAt(0))
                {
                    await XMLSerialize(t, outputStream.AsStreamForWrite());
                    await outputStream.FlushAsync();
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        public static async Task Serialize<T>(T t, string subPath, string fileName)
        {
            var folder = ApplicationData.Current.LocalFolder;
            var subFolder = await folder.GetFolderAsync(subPath);
            try
            {
                StorageFile file = await subFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
                using (IRandomAccessStream randomAccessSteam = await file.OpenAsync(FileAccessMode.ReadWrite))
                using (IOutputStream outputStream = randomAccessSteam.GetOutputStreamAt(0))
                {
                    await XMLSerialize(t, outputStream.AsStreamForWrite());
                    await outputStream.FlushAsync();
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private static async Task XMLSerialize<T>(T t, Stream stream)
        {
            try
            {
                var xml = new DataContractSerializer(typeof(T));
                await Task.Run(() => xml.WriteObject(stream, t));
            }
            catch (Exception)
            {
                throw;
            }
        }

        private static async Task<T> XMLDeserialize<T>(Stream stream) where T : class
        {
            try
            {
                var xml = new DataContractSerializer(typeof(T));
                object temp = null;
                await Task.Run(() =>
                {
                    temp = xml.ReadObject(stream);
                });
                return temp as T;
            }
            catch (System.InvalidOperationException)
            {
                return null;
                //return new T();
            }
            catch (Exception)
            {
                throw;
            }
        }

        public static async Task<TResult> Deserialize<TResult>(string fileName) where TResult : class
        {
            StorageFolder folder = ApplicationData.Current.LocalFolder;

            try
            {
                //if (await CheckFileExist(folder, fileName))
                //{
                StorageFile file = await folder.GetFileAsync(fileName);
                using (IRandomAccessStream randomAccessStream = await file.OpenAsync(FileAccessMode.Read))
                using (IInputStream inPutStream = randomAccessStream.GetInputStreamAt(0))
                {
                    return await XMLDeserialize<TResult>(inPutStream.AsStreamForRead());
                }
                //}
                //else { return null; }
            }
            catch (Exception ex)
            {
                //throw ex;
                return null;
            }
        }

        public static async Task<TResult> Deserialize<TResult>(string subPath, string fileName) where TResult : class
        {
            StorageFolder folder = ApplicationData.Current.LocalFolder;
            var subFolder = await folder.GetFolderAsync(subPath);

            try
            {
                //if (await CheckFileExist(folder, fileName))
                //{
                StorageFile file = await subFolder.GetFileAsync(fileName);
                using (IRandomAccessStream randomAccessStream = await file.OpenAsync(FileAccessMode.Read))
                using (IInputStream inPutStream = randomAccessStream.GetInputStreamAt(0))
                {
                    return await XMLDeserialize<TResult>(inPutStream.AsStreamForRead());
                }
                //}
                //else { return null; }
            }
            catch (Exception ex)
            {
                return null;
                //throw ex;
            }
        }
    }
}
